package com.njtoyo.taxi.admin.service.business.operation_rule.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njtoyo.taxi.admin.mapper.master.entity.DriverRegionServiceArrangement;
import com.njtoyo.taxi.admin.mapper.master.entity.GeoDriverRegion;
import com.njtoyo.taxi.admin.mapper.master.enums.DriverRegionServiceArrangementCategory;
import com.njtoyo.taxi.admin.mapper.master.mapper.DriverRegionServiceArrangementMapper;
import com.njtoyo.taxi.admin.mapper.master.mapper.GeoDriverRegionMapper;
import com.njtoyo.taxi.admin.rest.pojo.dto.RideCancelRuleDto;
import com.njtoyo.taxi.admin.rest.presenter.business.operation_rule.RideCancelRulePresenter;
import com.njtoyo.taxi.admin.service.business.operation_rule.RideCancelRuleService;
import com.njtoyo.taxi.entity.backend.AdminUser;
import com.taxi.entity.common.RestResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class RideCancelRuleServiceImpl implements RideCancelRuleService {
    @Autowired
    DriverRegionServiceArrangementMapper driverRegionServiceArrangementMapper;
    @Autowired
    GeoDriverRegionMapper driverRegionMapper;
    @Autowired
    private RedisTemplate redisTemplate;


    @Override
    public RestResult<IPage<RideCancelRulePresenter>> page(AdminUser adminUser, Integer current, Integer size, Long driverRegionId) {
        Page<DriverRegionServiceArrangement> page = new Page<>(current, size);
        DriverRegionServiceArrangement wrapper = new DriverRegionServiceArrangement();
        wrapper.setDriverRegionId(driverRegionId);
        wrapper.setServiceCategory(DriverRegionServiceArrangementCategory.ride_cancel_rule);
        IPage<DriverRegionServiceArrangement> pages = driverRegionServiceArrangementMapper.getPages(page, wrapper);

        List<GeoDriverRegion> regions = driverRegionMapper.selectList(null);
        List<RideCancelRulePresenter> cancelRulePresenters = new ArrayList<>();
        if (pages.getRecords().size() > 0) {
            Map<Long, GeoDriverRegion> toMap = regions.stream().collect(Collectors.toMap(GeoDriverRegion::getId, Function.identity()));
            for (DriverRegionServiceArrangement item : pages.getRecords()) {
                GeoDriverRegion geoDriverRegion = toMap.get(item.getDriverRegionId());
                RideCancelRulePresenter rideCancelRulePresenter = new RideCancelRulePresenter();
                rideCancelRulePresenter.setId(item.getId());
                rideCancelRulePresenter.setDriverRegionId(item.getDriverRegionId());
                if (ObjectUtil.isNotNull(geoDriverRegion)) {
                    rideCancelRulePresenter.setDriverRegionId(item.getDriverRegionId());
                    rideCancelRulePresenter.setDriverRegion(geoDriverRegion.getName());
                } else if (item.getDriverRegionId() == 0) {
                    rideCancelRulePresenter.setDriverRegion("默认");
                }
                JSONObject realtimeJson = JSON.parseObject(item.getDetailSpecification()).getJSONObject("realtime");
                if (realtimeJson != null) {
                    JSONObject freeCancelTimeJson = realtimeJson.getJSONObject("freeCancelTime");
                    if (ObjectUtil.isNull(freeCancelTimeJson)) continue;
                    RideCancelRulePresenter.RealtimeRule realtimeRule = new RideCancelRulePresenter.RealtimeRule();
                    realtimeRule.setCancelMinute(freeCancelTimeJson.getInteger("cancelMinute"));
                    realtimeRule.setCancelDailyTime(freeCancelTimeJson.getInteger("cancelDailyTime"));
                    JSONArray cancelDailyPeriodArray = freeCancelTimeJson.getJSONArray("cancelDailyPeriod");
                    realtimeRule.setCancelFreeStart(Convert.toInt(cancelDailyPeriodArray.get(0)));
                    realtimeRule.setCancelFreeEnd(Convert.toInt(cancelDailyPeriodArray.get(0)));

                    JSONArray cancelTimeArray = realtimeJson.getJSONArray("cancelTime");
                    JSONObject rule1 = JSON.parseObject(cancelTimeArray.get(0).toString());
                    JSONObject rule2 = JSON.parseObject(cancelTimeArray.get(1).toString());
                    JSONObject rule3 = JSON.parseObject(cancelTimeArray.get(2).toString());
                    JSONObject rule4 = JSON.parseObject(cancelTimeArray.get(3).toString());

                    //规则1
                    realtimeRule.setLadderOneMin(rule1.getInteger("waitTime"));
                    realtimeRule.setLadderOneAmount(rule1.getBigDecimal("penalty"));

                    //规则2
                    realtimeRule.setLadderTwoMin(rule2.getInteger("waitTime"));
                    realtimeRule.setLadderTwoAmount(rule2.getBigDecimal("penalty"));

                    //规则3
                    realtimeRule.setLadderThreeMin(rule3.getInteger("waitTime"));
                    realtimeRule.setLadderThreeAmount(rule3.getBigDecimal("penalty"));

                    //规则4
                    realtimeRule.setLadderFourMin(rule4.getInteger("waitTime"));
                    realtimeRule.setLadderFourAmount(rule4.getBigDecimal("penalty"));

                    rideCancelRulePresenter.setRealtime(realtimeRule);

                }
                JSONObject appointment = JSON.parseObject(item.getDetailSpecification()).getJSONObject("appointment");
                if (ObjectUtil.isNotNull(appointment)) {
                    RideCancelRulePresenter.AppointmentRule appointmentRule = new RideCancelRulePresenter.AppointmentRule();
                    appointmentRule.setDriverUnreached(new RideCancelRulePresenter.AppointmentRule.DriverUnreached().setFreeMin(appointment.getInteger("freeAppointmentTime"))
                            .setCancelTime(appointment.getJSONObject("driverUnreached").getInteger("cancelTime"))
                            .setAmount(appointment.getJSONObject("driverUnreached").getBigDecimal("penalty")));


                    JSONArray driverReached = appointment.getJSONArray("driverReached");
                    appointmentRule.setDriverReached(new RideCancelRulePresenter.AppointmentRule.DriverReached().setLadderOneMin(driverReached.getJSONObject(0).getInteger("cancelTime"))
                            .setLadderOneAmount(driverReached.getJSONObject(0).getBigDecimal("penalty"))
                            .setLadderTwoMin(driverReached.getJSONObject(1).getInteger("cancelTime"))
                            .setLadderTwoAmount(driverReached.getJSONObject(1).getBigDecimal("penalty")));

                    rideCancelRulePresenter.setAppointment(appointmentRule);
                }
                cancelRulePresenters.add(rideCancelRulePresenter);

            }
        }
        IPage<RideCancelRulePresenter> newPages = new Page<>();
        newPages.setRecords(cancelRulePresenters);
        newPages.setCurrent(pages.getCurrent());
        newPages.setSize(pages.getSize());
        newPages.setTotal(pages.getTotal());
        newPages.setPages(pages.getPages());
        return RestResult.success(newPages);
    }

    @Override
    public RestResult add(RideCancelRulePresenter rideCancelRulePresenter) {


        DriverRegionServiceArrangement selectOne = driverRegionServiceArrangementMapper.selectOne(Wrappers.<DriverRegionServiceArrangement>lambdaQuery()
                .eq(DriverRegionServiceArrangement::getServiceCategory, DriverRegionServiceArrangementCategory.ride_cancel_rule)
                .eq(DriverRegionServiceArrangement::getDriverRegionId, rideCancelRulePresenter.getDriverRegionId()));

        if (ObjectUtil.isNotNull(selectOne)) {
            return RestResult.failed("该区域已配置了规则");
        }

        JSONObject jsonObject = buildJson(rideCancelRulePresenter);
        DriverRegionServiceArrangement driverRegionServiceArrangement = new DriverRegionServiceArrangement();
        driverRegionServiceArrangement.setServiceCategory(DriverRegionServiceArrangementCategory.ride_cancel_rule);
        driverRegionServiceArrangement.setDriverRegionId(rideCancelRulePresenter.getDriverRegionId());
        driverRegionServiceArrangement.setIsOpen(true);
        driverRegionServiceArrangement.setDetailSpecification(jsonObject.toJSONString());
        driverRegionServiceArrangementMapper.insert(driverRegionServiceArrangement);

        //清缓存
        redisTemplate.delete("driver:service:arrangement");
        return RestResult.success();
    }

    @Override
    public RestResult update(RideCancelRulePresenter rideCancelRulePresenter) {
        driverRegionServiceArrangementMapper.selectOne(Wrappers.<DriverRegionServiceArrangement>lambdaQuery()
                .eq(DriverRegionServiceArrangement::getDriverRegionId, rideCancelRulePresenter.getDriverRegionId())
                .eq(DriverRegionServiceArrangement::getServiceCategory, DriverRegionServiceArrangementCategory.ride_cancel_rule)
                .not(i -> i.eq(DriverRegionServiceArrangement::getId, rideCancelRulePresenter.getId())));

        JSONObject jsonObject = buildJson(rideCancelRulePresenter);
        DriverRegionServiceArrangement update = new DriverRegionServiceArrangement();
        update.setId(rideCancelRulePresenter.getId());
        update.setDriverRegionId(rideCancelRulePresenter.getDriverRegionId());
        update.setDetailSpecification(jsonObject.toString());
        driverRegionServiceArrangementMapper.updateById(update);

        //清缓存
        redisTemplate.delete("driver:service:arrangement");
        return RestResult.success();
    }

    private JSONObject buildJson(RideCancelRulePresenter rideCancelRulePresenter) {

        RideCancelRuleDto.Realtime.CancelTime[] cancelTime = new RideCancelRuleDto.Realtime.CancelTime[]{
                new RideCancelRuleDto.Realtime.CancelTime(rideCancelRulePresenter.getRealtime().getLadderOneMin(), rideCancelRulePresenter.getRealtime().getLadderOneAmount()),
                new RideCancelRuleDto.Realtime.CancelTime(rideCancelRulePresenter.getRealtime().getLadderTwoMin(), rideCancelRulePresenter.getRealtime().getLadderTwoAmount()),
                new RideCancelRuleDto.Realtime.CancelTime(rideCancelRulePresenter.getRealtime().getLadderThreeMin(), rideCancelRulePresenter.getRealtime().getLadderThreeAmount()),
                new RideCancelRuleDto.Realtime.CancelTime(rideCancelRulePresenter.getRealtime().getLadderFourMin(), rideCancelRulePresenter.getRealtime().getLadderFourAmount())
        };

        RideCancelRuleDto dto = new RideCancelRuleDto();
        dto.setRealtime(new RideCancelRuleDto.Realtime().setFreeCancelTime(new RideCancelRuleDto.Realtime.FreeCancelTime()
                        .setCancelMinute(rideCancelRulePresenter.getRealtime().getCancelMinute()).setCancelDailyTime(rideCancelRulePresenter.getRealtime().getCancelDailyTime())
                        .setCancelDailyPeriod(new int[]{rideCancelRulePresenter.getRealtime().getCancelFreeStart(), rideCancelRulePresenter.getRealtime().getCancelFreeEnd()}))
                .setCancelTime(cancelTime));


        RideCancelRuleDto.Appointment.DriverReached[] driverReacheds = new RideCancelRuleDto.Appointment.DriverReached[]{
                new RideCancelRuleDto.Appointment.DriverReached(rideCancelRulePresenter.getAppointment().getDriverReached().getLadderOneMin(),rideCancelRulePresenter.getAppointment().getDriverReached().getLadderOneAmount()),
                new RideCancelRuleDto.Appointment.DriverReached(rideCancelRulePresenter.getAppointment().getDriverReached().getLadderTwoMin(),rideCancelRulePresenter.getAppointment().getDriverReached().getLadderTwoAmount())
        };
        dto.setAppointment(new RideCancelRuleDto.Appointment().setDriverUnreached(new RideCancelRuleDto.Appointment.DriverUnreached()
                        .setCancelTime(rideCancelRulePresenter.getAppointment().getDriverUnreached().getCancelTime())
                        .setPenalty(rideCancelRulePresenter.getAppointment().getDriverUnreached().getAmount()))
                .setFreeAppointmentTime(rideCancelRulePresenter.getAppointment().getDriverUnreached().getFreeMin())
                .setDriverWaitDefaultPenalty(new BigDecimal(2))
                .setDriverReached(driverReacheds));


        JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(dto));
        return jsonObject;

    }
}
